Guild icon
Project Sekai
🔒 CrewCTF 2023 / ❌-misc-jailpie
Avatar
jailpie - 1000 points
Category: Misc Description: who doesnt love jails? :Dwho doesnt love jails? :D Author : Fredd nc jailpie.chal.crewc.tf 8086 Files:Tags: No tags.
Sutx pinned a message to this channel. 07/07/2023 10:02 PM
Avatar
@unpickled admin bot wants to collaborate 🤝
Avatar
unpickled admin bot 07/07/2023 10:17 PM
fucking rar files?
Avatar
unpickled admin bot 07/07/2023 10:43 PM
this looks easy, but cryptoctfing, p much stolen chall from https://blog.splitline.tw/hitcon-ctf-2022/ (edited)
Feel free to share your writeup with me, especially those unintended solutions I didn't mentioned here! I'll put the link to your writeup into this blog post. Hi there. My team ⚔️TSJ⚔️ hosted HITCON CTF 2022 with HITCON & 217 this weekend, and I created 6 out of 27 challenges for
Avatar
unpickled admin bot 07/07/2023 10:57 PM
(set up an object brute while doing cryptoctf)
Avatar
unpickled admin bot 07/07/2023 11:07 PM
they didnt give py version
23:08
so praying 3.10.6
Avatar
unpickled admin bot 07/07/2023 11:17 PM
i have reason to believe it is not 3.10.6
23:17
fuck
23:20
oh
23:20
3.11
23:20
im blind
Avatar
unpickled admin bot 07/07/2023 11:55 PM
???????/
23:56
(code from: >>> n = 2403 >>> code = [ ... *([opmap['EXTENDED_ARG'], n // 256] ... if n // 256 != 0 else []), ... opmap['LOAD_NAME'], n % 256, ... opmap['RETURN_VALUE'], 0 ... ])
Avatar
unpickled admin bot 07/08/2023 12:10 AM
00:10
oob offsets
Avatar
unpickled admin bot 07/08/2023 12:24 AM
4821
00:24
but no fuckign getattr
00:24
where is it :<<<<<<<,
00:26
4947: attrgetter potential getattr alt
Avatar
unpickled admin bot 07/08/2023 12:48 AM
1031: __dict__ probable bypass if we can get a module (or smthng with __dict__) (edited)
00:50
6630: setattr perhaps useful
00:50
6735: type also maybe useful
Avatar
unpickled admin bot 07/08/2023 1:01 AM
7692: __delitem__ this can give us a none obj
01:01
which is very useful
01:02
7743: __class__ might as well save this
01:08
8208: f_globals saving this, but theres no way i get gi_frame and f_back too
01:12
8661: __import__
01:12
honestly
01:12
i might have enough
01:13
to just full send a standard payload (edited)
01:13
4632: __subclasses__
01:15
7509: __bases__
01:15
().__class__.__bases__[0].__subclasses__() i think this is the best avenue
01:16
8001: __dir__
Avatar
unpickled admin bot 07/08/2023 1:29 AM
237.77 KB
Avatar
@Violin wants to collaborate 🤝
Avatar
@Zafirr wants to collaborate 🤝
Avatar
@Rasser wants to collaborate 🤝
Avatar
omg really hard LOL i'm not used to pyjail
Avatar
Avatar
Rasser
omg really hard LOL i'm not used to pyjail
unpickled admin bot 07/08/2023 4:18 AM
this one is
04:18
a variant of hitcon 2022, void
04:18
the harder part would be the dis part
04:18
or perhaps building a payload with oob lets us not worry bout that
04:19
but in that case, we still need to build the payload :/
04:20
10k-20k
289.59 KB
Avatar
i think i have to read hitcon2022 write-ups
Avatar
@Legoclones wants to collaborate 🤝
Avatar
@Surg wants to collaborate 🤝
Avatar
unpickled admin bot 07/08/2023 1:21 PM
based on https://github.com/splitline/My-CTF-Challenges/blob/master/hitcon-ctf/2022/misc/void/exp/exp.py wanted to try import sys import unicodedata class Generator: # get numner def __call__(self, num): if num == 0: return '(not[[]])' return '(' + ('(not[])+' * num)[:-1] + ')' # get string def __getattribute__(self, name): try: offset = None.__dir__().index(name) return f'keys[{self(offset)}]' except ValueError: offset = None.__class__.__dir__(None.__class__).index(name) return f'keys2[{self(offset)}]' _ = Generator() names = [] chr_code = 0 for x in range(7744): while True: chr_code += 1 char = unicodedata.normalize('NFKC', chr(chr_code)) if char.isidentifier() and char not in names: try: print(char) names.append(char) except: continue break offsets = { "__class__": 7743, "__bases__": 7509, '__subclasses__': 4632, } #variables = ('keys', 'keys2', 'None_', 'NoneType', # 'm_repr', 'globals', 'builtins',) for name, offset in offsets.items(): names[offset] = name #for i, var in enumerate(variables): # assert var not in offsets # names[792 + i] = var source = f'''[ ({",".join(names)}) if [] else [], ().__class__.__bases__[{_(0)}].__subclasses__() ]'''.strip().replace('\n', '').replace(' ', '') #print(f"{len(source) = }", file=sys.stderr) #print(source) print(compile(source, "", "eval").co_code), however it syntax errors sadly
🏴 🏴 🏴. Contribute to splitline/My-CTF-Challenges development by creating an account on GitHub.
13:21
like [(A) if [] else [], <payload>] works ok
13:21
but not [(<all names needed> if [] else [], <payload>)
13:21
(not even on remote, it just syntax errolrs)
Avatar
Avatar
unpickled admin bot
based on https://github.com/splitline/My-CTF-Challenges/blob/master/hitcon-ctf/2022/misc/void/exp/exp.py wanted to try import sys import unicodedata class Generator: # get numner def __call__(self, num): if num == 0: return '(not[[]])' return '(' + ('(not[])+' * num)[:-1] + ')' # get string def __getattribute__(self, name): try: offset = None.__dir__().index(name) return f'keys[{self(offset)}]' except ValueError: offset = None.__class__.__dir__(None.__class__).index(name) return f'keys2[{self(offset)}]' _ = Generator() names = [] chr_code = 0 for x in range(7744): while True: chr_code += 1 char = unicodedata.normalize('NFKC', chr(chr_code)) if char.isidentifier() and char not in names: try: print(char) names.append(char) except: continue break offsets = { "__class__": 7743, "__bases__": 7509, '__subclasses__': 4632, } #variables = ('keys', 'keys2', 'None_', 'NoneType', # 'm_repr', 'globals', 'builtins',) for name, offset in offsets.items(): names[offset] = name #for i, var in enumerate(variables): # assert var not in offsets # names[792 + i] = var source = f'''[ ({",".join(names)}) if [] else [], ().__class__.__bases__[{_(0)}].__subclasses__() ]'''.strip().replace('\n', '').replace(' ', '') #print(f"{len(source) = }", file=sys.stderr) #print(source) print(compile(source, "", "eval").co_code), however it syntax errors sadly
unpickled admin bot 07/08/2023 1:24 PM
im dum
13:24
import sys import unicodedata class Generator: # get numner def __call__(self, num): if num == 0: return '(not[[]])' return '(' + ('(not[])+' * num)[:-1] + ')' # get string def __getattribute__(self, name): try: offset = None.__dir__().index(name) return f'keys[{self(offset)}]' except ValueError: offset = None.__class__.__dir__(None.__class__).index(name) return f'keys2[{self(offset)}]' _ = Generator() names = [] chr_code = 0 for x in range(7744): names.append(f"a{x}") offsets = { "__class__": 7743, "__bases__": 7509, '__subclasses__': 4632, } #variables = ('keys', 'keys2', 'None_', 'NoneType', # 'm_repr', 'globals', 'builtins',) for name, offset in offsets.items(): names[offset] = name #for i, var in enumerate(variables): # assert var not in offsets # names[792 + i] = var source = f'''[ ({",".join(names)}) if [] else [], ().__class__.__bases__[{_(0)}].__subclasses__() ]'''.strip().replace('\n', '').replace(' ', '') #print(f"{len(source) = }", file=sys.stderr) #print(source) print(compile(source, "", "eval").co_code.hex()) (edited)
Avatar
Avatar
unpickled admin bot
import sys import unicodedata class Generator: # get numner def __call__(self, num): if num == 0: return '(not[[]])' return '(' + ('(not[])+' * num)[:-1] + ')' # get string def __getattribute__(self, name): try: offset = None.__dir__().index(name) return f'keys[{self(offset)}]' except ValueError: offset = None.__class__.__dir__(None.__class__).index(name) return f'keys2[{self(offset)}]' _ = Generator() names = [] chr_code = 0 for x in range(7744): names.append(f"a{x}") offsets = { "__class__": 7743, "__bases__": 7509, '__subclasses__': 4632, } #variables = ('keys', 'keys2', 'None_', 'NoneType', # 'm_repr', 'globals', 'builtins',) for name, offset in offsets.items(): names[offset] = name #for i, var in enumerate(variables): # assert var not in offsets # names[792 + i] = var source = f'''[ ({",".join(names)}) if [] else [], ().__class__.__bases__[{_(0)}].__subclasses__() ]'''.strip().replace('\n', '').replace(' ', '') #print(f"{len(source) = }", file=sys.stderr) #print(source) print(compile(source, "", "eval").co_code.hex()) (edited)
unpickled admin bot 07/08/2023 1:42 PM
this failed the dis check
13:42
:<
Avatar
unpickled admin bot 07/08/2023 2:01 PM
ok we need to oob using LOAD_CONST
14:01
issue is
14:01
no build list?
14:02
we need to somehow convert the POP_JUMP_IF_FALSE to true
14:07
>>> cod = compile("[(a,b,c) if[]else []]","","exec") >>> dis(cod) 0 0 RESUME 0 1 2 BUILD_LIST 0 4 POP_JUMP_IF_FALSE 7 (to 20) 6 LOAD_NAME 0 (a) 8 LOAD_NAME 1 (b) 10 LOAD_NAME 2 (c) 12 BUILD_TUPLE 3 14 BUILD_LIST 1 16 POP_TOP 18 RETURN_CONST 0 (None) >> 20 BUILD_LIST 0 22 BUILD_LIST 1 24 POP_TOP 26 RETURN_CONST 0 (None) >>> this is some dis that would give oob, you can see theres alot of uh issues (edited)
Avatar
unpickled admin bot 07/08/2023 10:12 PM
ok i think
22:13
the idea here is to custom craft the bytecode so it loads a bunch of consts, then oob?
22:13
but how the fuck are const oobs abusable 😭
22:14
from types import CodeType from opcode import opmap from sys import argv class MockBuiltins(dict): def __getitem__(self, k): if type(k) == str: return k if __name__ == '__main__': n = int(argv[1]) code = [ *([opmap['EXTENDED_ARG'], n // 256] if n // 256 != 0 else []), opmap['LOAD_CONST'], n % 256, opmap['RETURN_VALUE'], 0 ] c = CodeType(0, 0, 0, 0, 0, 0, bytes(code), (0,), (), (), '', '', '', 0, b'', b'', (), ()) ret = eval(c, {'__builtins__': MockBuiltins()}) if ret: print(f'{n}: {ret}') ig i can just
22:14
run this and pray?
Avatar
Avatar
unpickled admin bot
4632: __subclasses__
unpickled admin bot 07/08/2023 10:15 PM
smthng diff i think?
22:15
but
22:15
still oob
22:15
ill take it
Avatar
unpickled admin bot 07/08/2023 10:26 PM
ngl i got no idea how imma include this in a payload
22:26
like classes
22:27
78: {'__module__': 'contextlib', '__name__': '_create_exit_wrapper', '__qualname__': '_BaseExitStack._create_exit_wrapper', '__doc__': None, '__annotations__': {}} huh
22:27
HUH???????/
22:27
wtf
22:28
ngl it should give me a dictionary for os pls python thanks
22:33
motivation
Avatar
unpickled admin bot 07/08/2023 10:33 PM
uh
22:36
no EXTENDED_ARG either :pain:
22:36
but it is prob hand crafted (i.e not just compile(smthng).co_code) const oob payload (edited)
Avatar
unpickled admin bot 07/08/2023 11:22 PM
23:23
very useful constant
23:23
if i may say so myself
23:23
all of builtins? we take those
23:23
fun lil issue tho
23:23
even though we have builtins dict
23:23
which should be lovely
23:24
we even have the str 3487: __loader__ (or perhaps the const, im not sure) (edited)
23:24
we dont have the strings
23:24
like
23:24
breakpoint
23:24
we need that
23:24
and
23:25
whitelist = { 'LOAD_CONST', 'BINARY_OP', 'COMPARE_OP', 'POP_JUMP_BACKWARD_IF_TRUE', 'RETURN_VALUE', }
23:25
very unfun whitelist
23:25
3987: __getattribute__ 3988: <slot wrapper '__getattribute__' of 'functools.partial' objects>
23:25
ngl
23:26
this might be my first fuckign getattr
23:28
4138: <_frozen_importlib_external.SourceFileLoader object at 0xffffb2d81dd0> loader obj
23:29
4300: <module 'builtins' (built-in)> the module
23:31
4548: <module 'os' (frozen)> oooooooooooooooooooo
23:31
thats a fun const
23:31
big issue tho is
23:31
even if we can load anythibgn
23:32
like builtins
23:32
loader
23:32
os
23:32
how the fuck os.system (edited)
23:32
i would guess a large amount of getattr shennanigins
23:33
189.28 KB
23:33
if anyone else wanna suffer theres the consts so far (edited)
23:34
wait is this going to fyck with my const idxs (edited)
23:35
...................................................
23:35
it better fucking not
23:35
oob with constants gonna be so hard
23:35
f u c k
23:35
ok
23:35
i guess
23:35
the best approach is
23:36
import everything the jail does
23:36
in the same order
23:36
and
23:36
then pray
23:37
but i need opcodes??????????????????????????????????????????????????
23:37
ok uhuhuhuhuhuh
23:37
f u c k
23:38
ok
23:38
some stuff stays the same
23:38
(code.py had earlier imports + a random const added)
23:38
ok
23:38
everything before
23:38
is the same
23:38
(before main)
23:38
after that
23:39
all shit goes to hell!
23:40
apport_excepthook forgot this was a thing lmao (edited)
23:40
nice to know tho
23:42
190.34 KB
23:42
these are all the consistent consts
23:42
(at least i hope)
23:42
the jails fucking 3.11 right
Avatar
unpickled admin bot 07/09/2023 1:50 AM
:/ ok dis is kinda hell
01:50
since i can jump, load, compare, and return
01:50
none of which let me use my getattr
Avatar
Avatar
unpickled admin bot
none of which let me use my getattr
unpickled admin bot 07/09/2023 1:55 AM
which means i cant use any of the stuff i got? (edited)
Avatar
@kanon wants to collaborate 🤝
Avatar
@unpickled admin bot
Avatar
unpickled admin bot 07/09/2023 2:41 PM
:<
Exported 151 message(s)